/**
 * @filename:SwitchOrderInfoController 2020年06月11日
 * @project hotel-switch  V1.0
 * Copyright(c) 2020 Zhang·JZ Co. Ltd.
 * All right reserved.
 */
package hotel.switchs.oversea.biz.controller.order;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import hotel.base.oversea.constant.CommonConstants;
import hotel.base.oversea.constant.enums.CommonEnums;
import hotel.base.oversea.dto.switchs.SwitchOrderInfoDto;
import hotel.base.oversea.utils.DateUtil;
import hotel.base.oversea.utils.Result;
import hotel.base.oversea.vo.meituan.response.order.MtHotelOrderCheckVo;
import hotel.switchs.oversea.api.VO.order.OperateDltOrder;
import hotel.switchs.oversea.api.VO.order.ReturnDltOrderInfoCheckVo;
import hotel.switchs.oversea.api.VO.request.RequestCheckOrderVo;
import hotel.switchs.oversea.api.VO.request.RequestOrderMotifyVo;
import hotel.switchs.oversea.biz.config.RedisLock;
import hotel.switchs.oversea.biz.config.service.RedisService;
import hotel.switchs.oversea.biz.service.SwitchOrderInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 *@Description: 携程订单控制类
 *@Author: Zhang·jz
 *@date: 2020/6/8
 */
@Slf4j
@RestController
@RequestMapping("/switchOrderInfo")
@Api(value = "switchOrderController",tags = {"获取携程订单信息接口"})
public class SwitchOrderInfoController {
    @Autowired
    RedisLock redisLock;
    @Autowired
    RedisService redisService;
    @Autowired
    SwitchOrderInfoService switchOrderInfoService;

    /**
     * 订单变化通知接口
     * 参考携程订单接口文档 7.1
     * 注：每分钟调用不得超过 10 次
     * @param requestOrderMotifyVO
     * @return
     */
    @PostMapping("/getdltordernotify")
    @ApiOperation(value = "订单变化通知接口",notes="必须经过auth授权")
    @ApiImplicitParam(name = "requestOrderMotifyVO", value = "requestOrderMotifyVO", required = true, dataType = "RequestOrderMotifyVo")
    public Result<Object> getdltordernotify(@RequestBody RequestOrderMotifyVo requestOrderMotifyVO){


        if(ObjectUtils.isEmpty(requestOrderMotifyVO)){
            return new Result<>(CommonEnums.FIELD_NULL);
        }

        //发起请求并保存数据
        return  switchOrderInfoService.getdltordernotify(requestOrderMotifyVO);
    }


    /**
     * 订单详情接口
     * 参考携程订单接口文档 7.2
     * 注：每分钟调用不得超过 10 次
     * @param dltOrderId
     * @return
     */
    @GetMapping("/getdltorderinfo/{dltOrderId}")
    @ApiOperation(value = "订单详情接口",notes="必须经过auth授权")
    @ApiImplicitParam(name = "dltOrderId", value = "dltOrderId", required = true, dataType = "String")
    public Result<Object> getdltorderinfo(@PathVariable("dltOrderId") String dltOrderId){
        if (ObjectUtils.isEmpty(dltOrderId)) {
            return new Result<>(CommonEnums.FIELD_NULL);
        } else {
            return switchOrderInfoService.getdltorderinfo(dltOrderId);
        }
    }


    /**
     * 订单操作接口
     * 参考携程订单接口文档 7.3.
     * 注：每分钟调用不得超过 10 次
     * @param operateDltOrder
     * @return
     */
    @PostMapping("/operaterDltOrder")
    @ApiOperation(value = "订单操作接口",notes="必须经过auth授权")
    @ApiImplicitParam(name = "operateDltOrder", value = "operateDltOrder", required = true, dataType = "OperateDltOrder")
    public Result<Object> operaterDltOrder(@RequestBody OperateDltOrder operateDltOrder){

        if (ObjectUtils.isEmpty(operateDltOrder)) {
            return new Result<>(CommonEnums.FIELD_NULL);
        } else {
            return switchOrderInfoService.operaterDltOrder(operateDltOrder);
        }
    }


    /**
     * 发单接口
     * 将订单发送给相关酒店供应商
     * 参考携程订单接口文档 7.4.
     * 注：每分钟调用不得超过 10 次
     * @return
     */
    @PostMapping("/issueOrder")
    @ApiOperation(value = "发单接口 将订单发送给相关酒店供应商 ",notes="必须经过auth授权")
    @ApiImplicitParam(name = "orderId", value = "orderId", required = true, dataType = "String")
    public Result<Object> issueOrder(@RequestBody JSONObject jsonObject) {

        if (ObjectUtils.isEmpty(jsonObject.get("orderId"))) {
            return new Result<>(CommonEnums.FIELD_NULL);
        } else {
            return new Result<>(CommonConstants.SUCCESS);
//            return switchOrderInfoService.issueOrder(jsonObject.get("orderId").toString());
        }
    }



    /**
     * 订单列表查询接口
     * 参考携程订单接口文档 7.5.
     * 注：每分钟调用不得超过 10 次
     * @param requestCheckOrderVo
     * @return List<ReturnDltOrderInfoCheckVo>
     */
    @GetMapping("/getDltOrderList")
    @ApiOperation(value = "订单列表查询接口",notes="必须经过auth授权")
    @ApiImplicitParam(name = "requestCheckOrderVo", value = "requestCheckOrderVo", required = true, dataType = "RequestCheckOrderVo")
    public Result<List<ReturnDltOrderInfoCheckVo>> getDltOrderList(@RequestBody RequestCheckOrderVo requestCheckOrderVo){

        if (ObjectUtils.isEmpty(requestCheckOrderVo)) {
            return new Result<>(CommonEnums.FIELD_NULL);
        } else {
            return switchOrderInfoService.getDltOrderList(requestCheckOrderVo);
        }
    }

    /**
     * 操作携程和美团订单
     * 注：每分钟调用不得超过 10 次
     * @return
     */
    @PostMapping("/operateSwitchAndMeituanOrderByOrderId")
    @ApiOperation(value = "订单详情接口",notes="必须经过auth授权")
    @ApiImplicitParam(name = "md5key", value = "md5key", required = true, dataType = "String")
    public Result<Object> aspoperateSwitchAndMeituanOrderByOrderId(@RequestBody JSONObject jsonObject){
        if (ObjectUtils.isEmpty(jsonObject.get("md5key"))) {
            return new Result<>(CommonEnums.FIELD_NULL);
        } else {
            Result rs = checkRedisFpOrderId(jsonObject.get("md5key").toString());
            if(rs.getCode()==CommonConstants.SUCCESS){
                return switchOrderInfoService.operateSwitchAndMeituanOrderByOrderId(jsonObject.get("md5key").toString());
            }else{
                return rs;
            }
        }
    }

    /**
     * 缓存锁，判断短时间内订单号重复
     * @Author qyy
     * @return
     */
    private Result checkRedisFpOrderId(String id) {
        Boolean check = false;
        Date date = DateUtil.addSecond(DateUtil.getCurrTime(),3);
        String timestamp = DateUtil.dateToStamp(DateUtil.formatDate(date,"yyyy-MM-dd HH:mm:ss"));
        String key = "swmt_redis_order_apply_order_id_delay_again";
        if(null == redisService.get(key+id)){
            log.info("null REDIS_ORDER_APPLY_FP_ORDER_ID+fpOrderId={}",key+id);
            try{
                boolean lock1 = redisLock.lock(key+id,timestamp);
                if(lock1){
                    log.info("null REDIS_ORDER_APPLY_FP_ORDER_ID+fpOrderId 枷锁成功，更新缓存token ");
                    //枷锁成功，更新缓存token
                    redisService.setUnit(key+id,"1",1L, TimeUnit.MINUTES);
                    //解锁
                    redisLock.release(key+id,timestamp);
                }else{
                    //如果枷锁失败  很大可能是被其他线程枷锁，sleep后再获取redistoken
                    try {
                        Thread.sleep(200);
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                    }
                    log.error("sw_delay_orders_to_booking_get_ids，加锁失败");
                    if(null != redisService.get(key+id)){
                        log.error("sw_delay_orders_to_booking_get_ids，存在该订单号 1 id={}",key+id);
                        check = true;//存在该订单号
                    }
                }
            }catch (Exception e){
                log.info("sw_delay_orders_to_booking_get_ids 异常catch :"+e.getMessage());
                e.printStackTrace();
            }
        }else{
            log.error("sw_delay_orders_to_booking_get_ids，存在该订单号 2 id={}",key+id);
            check = true;//存在该订单号
        }
        if(check){
            return new Result("[REDIS-CHECK-ERROR]短时间内该订单号重复提交",CommonConstants.REQUEST_ERROR);
        }else{
            return new Result();
        }
    }

    /**
     * 修改携程订单相关根据美团下单前校验code
     */
    @PostMapping("/updateSwitchsOrderByMtBookingBeforeCode")
    @ApiOperation(value = "修改携程订单相关根据美团下单前校验code",notes="必须经过auth授权")
    @ApiImplicitParam(name = "map", value = "map", required = true, dataType = "map")
    public Result<Object> aspupdateSwitchsOrderByMtBookingBeforeCode(@RequestBody Map map){
        SwitchOrderInfoDto switchOrderInfoDto = JSON.parseObject((String)map.get("switchOrderInfoDto"),SwitchOrderInfoDto.class);
        MtHotelOrderCheckVo mtHotelOrderCheckVo = JSON.parseObject((String)map.get("mtHotelOrderCheckVo"), MtHotelOrderCheckVo.class);
        return switchOrderInfoService.updateSwitchsOrderByMtBookingBeforeCode(switchOrderInfoDto,mtHotelOrderCheckVo);
    }

}
